package relu.R.landscape;

import java.util.List;

public class FarmArea {
	private final SpatialLandscape landscape;
	public double xPos;
	public double yPos;
	public final double radius;
	public	final double LParea;
	private double xforce=0;
	private double yforce=0;
	
	public FarmArea(SpatialLandscape landscape_,double x,double y,double a){
		xPos=x;
		yPos=y;
		LParea=a;
		radius=Math.sqrt(a/3.141592);
		
		landscape=landscape_;
	}

	public void setPos(double x,double y){
		xPos=x;
		yPos=y;
	}
	
//	public void setRadius(double r){radius=r;};
	
	

	public void move(){
		xPos+=xforce*0.01+(SpatialLandscape.rGen.nextDouble()-0.5)*0.0001;
		xPos=SpatialLandscape.foldCoordinate(landscape.sideLength, xPos);
		yPos+=yforce*0.01+(SpatialLandscape.rGen.nextDouble()-0.5)*0.0001;
		yPos=SpatialLandscape.foldCoordinate(landscape.sideLength, yPos);
	}
	
	public void calculateForces(List<FarmArea> farms){
		xforce=0;
		yforce=0;
		for(FarmArea farm:farms){
			double[] force=calculateForceVector(this,farm);
			xforce+=force[0];
			yforce+=force[1];
		}
	//	System.out.println("Total Force: "+xforce+" "+yforce);
	}
	
	public double minImageDistance(double boxl,double d){
		if ( d > boxl/2){
			return d-boxl;
		} 
		if ( d < -boxl/2){
			return d+boxl;
		}
		return d;
	}
	
	public double[] calculateForceVector(FarmArea from,FarmArea to){
		if (from==to){return (new double[]{0.0,0.0});};
		double boxl=landscape.sideLength;
		
//		double dx=Landscape.foldCoordinate(boxl,(from.xPos-to.xPos));
//		double dy=Landscape.foldCoordinate(boxl, (from.yPos-to.yPos));
		double dx=minImageDistance(boxl,(from.xPos-to.xPos));
		double dy=minImageDistance(boxl,(from.yPos-to.yPos));
		
		double dist=(Math.sqrt(dx*dx+dy*dy));
		double desiredDistance=from.radius+to.radius;
		double pairForce=pairForce(dist,desiredDistance);
		double[] fvec=new double[]{(dx*pairForce)/dist,(dy*pairForce)/dist};
	//	System.out.println("Fvec d:"+dist+" "+fvec[0]+" "+fvec[1]+" "+pairForce);
		return fvec;
	}
	
	public double pairForce(double d,double req){
		double max=Math.exp(-(d-req));
		if ( (d-req) > 0 ){
			return 0;
		} else {
			return(Math.min(max, 1000));
		}
	}
	
}
